package com.hnblc.blcwms.rest.controller;

import com.fasterxml.jackson.core.type.TypeReference;
import com.hnblc.blcwms.common.constant.StringPool;
import com.hnblc.blcwms.common.exceptions.ErrorDescription;
import com.hnblc.blcwms.common.exceptions.GeneralException;
import com.hnblc.blcwms.common.interaction.Response;
import com.hnblc.blcwms.common.interaction.RestResponse;
import com.hnblc.blcwms.common.utils.encrypt.BASE64;
import com.hnblc.blcwms.persistent.interfaces.business.entity.ExpLog;
import com.hnblc.blcwms.persistent.interfaces.business.service.IExpLogService;
import com.hnblc.blcwms.persistent.interfaces.client.dto.CurrentClient;
import com.hnblc.blcwms.persistent.interfaces.client.entity.ClientAuth;
import com.hnblc.blcwms.persistent.interfaces.message.entity.MessageLog;
import com.hnblc.blcwms.persistent.interfaces.sysConfig.service.IFieldDictionaryService;
import com.hnblc.blcwms.rest.dto.restInteraction.EncryptRequest;
import com.hnblc.blcwms.rest.dto.restInteraction.ReadableRequest;
import com.hnblc.blcwms.rest.service.IMessageService;
import com.hnblc.blcwms.serviceapi.api.dto.WareHouseOperate;
import com.hnblc.blcwms.serviceapi.api.dto.ration.cancel.ExpressCancel;
import com.hnblc.blcwms.serviceapi.api.dto.ration.note.ExpressHead;
import com.hnblc.blcwms.serviceapi.api.enums.code.ExpLogTypeEnum;
import com.hnblc.blcwms.serviceapi.api.enums.result.log.CreateExpLogResultEnum;
import com.hnblc.blcwms.serviceapi.api.group.custom.CustomsGroup;
import com.hnblc.blcwms.serviceapi.api.group.custom.express.ExpB2CGroup;
import com.hnblc.blcwms.serviceapi.api.group.custom.express.ExpGroup;
import com.hnblc.blcwms.serviceapi.api.service.IRationNoteAPIService;
import com.hnblc.blcwms.serviceapi.odata.IExpressService;
import com.hnblc.blcwms.serviceapi.odata.enums.code.ExpMTypeEnum;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;


@Setter
@Getter
@RestController
@RequestMapping("blc/wms/api/order")
@Api(value="通用出库通知单API",description = "线上订单、门店配送等交易方式出库通知单相关操作",tags={"出库单通知接口"})
@Validated
public class OrderRestAPI extends BaseRestAPI {

    public static Logger logger = LoggerFactory.getLogger(OrderRestAPI.class);

    @Value("sys.interface.config.max-over-time")
    private String requestMaxOverTime;

    @Autowired
    IMessageService messageService;

    @Autowired
    IExpressService expressService;

    @Autowired
    IRationNoteAPIService rationNoteAPIService;

    @Autowired
    IExpLogService expLogService;

    @Autowired
    IFieldDictionaryService fieldDictionaryService;

//    @ApiOperation(value="创建出货单", notes="根据客户OMS或商城产生的订单生成出货单",position = 1)
//    @RequestMapping(value = "/explicit_create" ,method = RequestMethod.POST)
//    @ResponseBody
    public RestResponse<Boolean> explicit_create(@Validated({CustomsGroup.class}) @RequestBody ReadableRequest<WareHouseOperate<ExpressHead>> commonParam, HttpServletRequest request) {
        //接口鉴权
        ClientAuth clientAuth = this.buildAuth(commonParam);
        CurrentClient currentClient = this.clientInfoService.loadCurrentClient(clientAuth);
        if (null == currentClient || currentClient.getClientAuthInfo().size() < 1) {
            return new RestResponse(new GeneralException(ErrorDescription.ERROR_REQUEST_CLIENT_UNAUTHORIZED_0));
        }
        MessageLog messageLog = messageService.process(currentClient, request);
        //直接创建出货单，暂时作废，将数据保存到缓冲表中
        Response<Boolean> result= expressService.createExpress(commonParam.getBusinessData().getOperateDetails(),clientAuth);

        ExpLog expLog = new ExpLog(ExpLogTypeEnum.CREATE.code(),clientAuth.getClientId(),messageLog.getSeqNo(),commonParam.getBusinessData().getOperateDetails().getSourceExpNo(),result);
        if(!expLogService.save(expLog)){
            new RestResponse<>(new Response(CreateExpLogResultEnum.CREATE_ERROR_SAVE_FAIL));
        }
        messageService.processed(messageLog);
        return new RestResponse<>(result);
    }

    @ApiOperation(value="通用创建出货单", notes="根据客户OMS或商城产生的订单生成出货单",position = 3)
    @RequestMapping(value = "/create" ,method = RequestMethod.POST)
    @ResponseBody
    public RestResponse<Boolean> create(@Validated({ExpGroup.class}) @RequestBody EncryptRequest message, HttpServletRequest request) throws IOException {
        //测试打印原始报文
        String jsonString = IOUtils.toString(request.getInputStream(), Charset.defaultCharset());
        logger.debug("***********************************create test start***************************\n"+jsonString+"\n*********************end*************************");

        //解析业务数据 从BASE64字符串解析为JSON字符串，再解析为业务对象
        WareHouseOperate<ExpressHead> businessData;
        try {
            businessData = objectMapper.readValue(new String(BASE64.decryptBASE64(message.getBusinessData()), StringPool.CHARSET_UTF8),new TypeReference<WareHouseOperate<ExpressHead>>() { });
        }catch (Exception e){
            return new RestResponse<>(new GeneralException(ErrorDescription.ERROR_REQUEST_BAD_PARAMETER_FORMAT_0,e));
        }

        if (ExpMTypeEnum.B2C.code().equals(businessData.getOperateDetails().getExpType())
            || ExpMTypeEnum.B2C1.code().equals(businessData.getOperateDetails().getExpType())){
            //电商出货验证
            this.validate(businessData, ExpB2CGroup.class);
        }else {
            //其他出货验证
            this.validate(businessData, ExpGroup.class);
        }

        //校验操作权限
        ClientAuth clientAuth = this.buildAuth(message,businessData);
        CurrentClient currentClient = this.clientInfoService.loadCurrentClient(clientAuth);
        if (null == currentClient || currentClient.getClientAuthInfo().size() < 1) {
            return new RestResponse<>(new GeneralException(ErrorDescription.ERROR_REQUEST_CLIENT_UNAUTHORIZED_0));
        }

        //验签
        try {
            if (!this.signatureValidate(message, currentClient)) {
                return new RestResponse<>(new GeneralException(ErrorDescription.ERROR_REQUEST_SIGNATURE_VALIDATE_FAIL_0));
            }
        } catch (Exception e) {
            logger.error("接口处理验签异常", e);
            throw new GeneralException(e);
        }
        MessageLog messageLog = messageService.process(currentClient, request);

        //创建出货通知单，接收成功后，内件原因暂存，入出货通知单暂存表
        Response<Boolean> result= rationNoteAPIService.createRationNote(businessData.getOperateDetails(),currentClient.getClientAuthInfo().get(0));
        //保存创建日志，如果没有则无法反馈发货状态
        ExpLog expLog = new ExpLog(ExpLogTypeEnum.CREATE.code(),message.getClientId(),messageLog.getSeqNo(),businessData.getOperateDetails().getSourceExpNo(),result);
        if(!expLogService.save(expLog)){
            logger.error("Error occurred when save [RATION NOTE] creation log to database");
        }
        messageService.processed(messageLog);
        return new RestResponse<>(result);
    }


    @ApiOperation(value="批量取消出货单", notes="批量取消已收到未开始操作的出货单",position = 4)
    @RequestMapping(value = "/cancel/batch" ,method = RequestMethod.POST)
    @ResponseBody
    public RestResponse cancelExpress(@Validated({ExpGroup.class})@RequestBody ReadableRequest<WareHouseOperate<List<ExpressCancel>>> commonParam, HttpServletRequest request) {
        RestResponse<List<ExpressCancel>> res = new RestResponse(true);
        ClientAuth clientAuth = this.buildAuth(commonParam);
        CurrentClient currentClient = this.clientInfoService.loadCurrentClient(clientAuth);
        if (null == currentClient || currentClient.getClientAuthInfo().size()<1) {
            res.initError(new GeneralException(ErrorDescription.ERROR_REQUEST_CLIENT_UNAUTHORIZED_0));
            return res;
        }

        /*try {
            if (!this.signatureValidate(commonParam,currentClient)){
                return new RestResponse<>(new GeneralException(ErrorDescription.ERROR_REQUEST_SIGNATURE_VALIDATE_FAIL_0));
            }
        }catch (Exception e){
            logger.error("接口处理验签异常",e);
            throw new GeneralException(e);
        }*/

        //报文落地保存
        //取消订单操作
        MessageLog messageLog = messageService.process(currentClient, request);
        List<ExpressCancel> errorOrders= rationNoteAPIService.cancelOrders(clientAuth,commonParam.getBusinessData().getOperateDetails(),messageLog.getSeqNo());
        //更新处理状态
        messageService.processed(messageLog);
        if (errorOrders!=null && errorOrders.size()>0){
            res.initError(new GeneralException(ErrorDescription.ERROR_REQUEST_BUSINESS_ERROR_0));
            res.setBusiness_data(errorOrders);
        }
        return res;
    }







}
